package com.baomidou.springwind.controller.supply;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.kisso.annotation.Permission;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.springwind.controller.BaseController;
import com.baomidou.springwind.controller.NodeData;
import com.baomidou.springwind.entity.*;
import com.baomidou.springwind.mapper.NetworkDeliveryDao;
import com.baomidou.springwind.mapper.OrderDataDao;
import com.baomidou.springwind.pojo.SiteCoverBuilder;
import com.baomidou.springwind.pojo.SiteSelection;
import com.baomidou.springwind.pojo.SiteSelectionBuilder;
import com.baomidou.springwind.pojo.SiteSelectionBuilderTwo;
import com.baomidou.springwind.service.NetworkSupplyService;
import com.baomidou.springwind.service.OrderDataService;
import com.baomidou.springwind.service.ProjectService;
import com.baomidou.springwind.service.NetworkDeliveryService;
import com.baomidou.springwind.utils.CityUtil;
import com.baomidou.springwind.utils.ParamMap;
import com.baomidou.springwind.utils.ZvalueUtil;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.baomidou.springwind.mapper.NetworkSupplyDao;
import com.baomidou.springwind.mapper.NetworkPlanningDao;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

@Controller
@RequestMapping("/network/supply")
public class AlgorithmTwoController extends BaseController{
    @Autowired
    private NetworkSupplyService networkSupplyService;

    @Autowired
    private NetworkSupplyDao networkSupplyDao;

    @Autowired
    private NetworkDeliveryDao networkDeliveryDao;

    @Autowired
    private NetworkDeliveryService networkDeliveryService;

    @Autowired
    private OrderDataService orderDataService;

    @Autowired
    private OrderDataDao orderDataDao;

    @Autowired
    private NetworkPlanningDao networkPlanningDao;

    @Autowired
    private ProjectService projectService;

    private DecimalFormat df = new DecimalFormat("###,##0.00");

    /**
     * 客户分析主界面
     */
    @RequestMapping("/algorithm2")
    @Permission("1001")
    public String algorithm(Model model) {

        return pjaxPath("/lpp/network/supply/algorithmTwo/main",model);
    }

    //获取radio
    @ResponseBody
    @Permission("1001")
    @RequestMapping("/algorithm2/radio")
    public String radio() {
        EntityWrapper<NetworkDelivery> wrapper = new EntityWrapper<NetworkDelivery>();
        wrapper.setSqlSelect("lnglat_id id,name");
        wrapper.eq("operator_id",getCurrentUserId());
        wrapper.eq("batch_id",getProjectId());
        wrapper.eq("type",1);
        List<NetworkDelivery> networkDeliveryList=networkDeliveryDao.selectList(wrapper);
        JSONObject ret = new JSONObject();
        ret.put("radio",networkDeliveryList);
        return callbackSuccess(ret);
    }
    //生成一个表数据
    @ResponseBody
    @Permission("1001")
    @RequestMapping("/algorithm2/newData")
    public String newTable() {
        ParamMap<String, Object> pm0 = getParameterMap();
        String radioFalse=pm0.get("false").toString();
        String radioTrue=pm0.get("true").toString();
        String id="1000000"+getProjectId();

        if(pm0.get("name").toString().length()==0){
            //删除数据
            deleteid(id);
        }

        //没有被选中的集合
        String rFalse[] =radioFalse.split(",");
        EntityWrapper<NetworkDelivery> wrapper0 = new EntityWrapper<NetworkDelivery>();
        wrapper0.in("lnglat_id",rFalse);
        wrapper0.eq("batch_id",getProjectId());
        List<NetworkDelivery> list0=networkDeliveryService.selectList(wrapper0);


        Boolean boolean1=false;
        if(pm0.get("name").toString().length()==0){
            createNetworkDelivery(id);
            createOrderData(id);
            boolean1=updateId(id,radioFalse,radioTrue);
        }
        if(pm0.get("name").toString().length()>0){
            boolean1=true;
        }

        if(boolean1){
            //算法结果
            JSONObject data=getResult(id,list0);
            return callbackSuccess(data);
        }
        return callbackFail("数据失败");
    }
    public void createOrderData(String id){
        //创建OrderData
        EntityWrapper<OrderData> wrapper1 = new EntityWrapper<OrderData>();
        wrapper1.eq("operator_id",getCurrentUserId());
        wrapper1.eq("batch_id",getProjectId());
        List<OrderData> orderDataList=orderDataService.selectList(wrapper1);
        for (int i=0;i<orderDataList.size();i++){
            orderDataList.get(i).setBatchId(Long.valueOf(id));
            orderDataList.get(i).setId(null);
        }
        orderDataService.insertBatch(orderDataList,100);
    }

    /**
     * 复制该id下的信息
     * @param id
     */
    public void createNetworkDelivery(String id){
        //创建NetworkDelivery
        EntityWrapper<NetworkDelivery> wrapper = new EntityWrapper<NetworkDelivery>();
        wrapper.eq("operator_id",getCurrentUserId());
        wrapper.eq("batch_id",getProjectId());
        wrapper.eq("type",1);
        List<NetworkDelivery> list=networkDeliveryDao.selectList(wrapper);
        for (int i=0;i<list.size();i++){
            Long id1=list.get(i).getId();

            //新建一个一级配送中心
            NetworkDelivery networkDelivery=new NetworkDelivery();
            networkDelivery=list.get(i);
            networkDelivery.setBatchId(Long.valueOf(id));
            networkDelivery.setId(null);
            networkDeliveryService.insert(networkDelivery);

            //查询到新建一级中心的ID
            EntityWrapper<NetworkDelivery> wrapper1 = new EntityWrapper<NetworkDelivery>();
            wrapper1.eq("operator_id",getCurrentUserId());
            wrapper1.eq("batch_id",id);
            wrapper1.eq("type",1);
            wrapper1.eq("lnglat_id",networkDelivery.getLnglatId());
            NetworkDelivery networkDelivery1=networkDeliveryService.selectOne(wrapper1);

            //查询到该一级中心下的所有二级中心
            EntityWrapper<NetworkDelivery> wrapper2 = new EntityWrapper<NetworkDelivery>();
            wrapper2.eq("operator_id",getCurrentUserId());
            wrapper2.eq("batch_id",getProjectId());
            wrapper2.eq("type",2);
            wrapper2.eq("pid",id1);
            List<NetworkDelivery> networkDeliveryList2=networkDeliveryService.selectList(wrapper2);

            //修改所有二级中心的属性，并且保存
            for(int i1=0;i1<networkDeliveryList2.size();i1++){
                networkDeliveryList2.get(i1).setId(null);
                networkDeliveryList2.get(i1).setpId(networkDelivery1.getId());
                networkDeliveryList2.get(i1).setBatchId(Long.valueOf(id));
            }
            if(networkDeliveryList2.size()>0){
                networkDeliveryService.insertBatch(networkDeliveryList2,100);
            }
        }

    }

    /**
     * 删除batch_id是id的NetworkDelivery OrderData
     * @param id
     */
    public void deleteid(String id){
        EntityWrapper<NetworkDelivery> wrapper2 = new EntityWrapper<NetworkDelivery>();
        wrapper2.eq("batch_id",id);
        networkDeliveryService.delete(wrapper2);
        EntityWrapper<OrderData> wrapper3 = new EntityWrapper<OrderData>();
        wrapper3.eq("batch_id",id);
        orderDataService.delete(wrapper3);
    }

    /**
     * 修改batch_id是id的NetworkDelivery  OrderData表的信息
     * @param id
     * @param radioFalse
     * @param radioTrue
     * @return
     */
    public Boolean updateId(String id,String radioFalse,String radioTrue){
        String rFalse[] =  radioFalse.split(",");
        String rTrue[] = radioTrue.split(",");

        EntityWrapper<NetworkDelivery> wrapper = new EntityWrapper<NetworkDelivery>();
        wrapper.in("lnglat_id",rTrue);
        wrapper.eq("batch_id",id);
        List<NetworkDelivery> ListTrue=networkDeliveryService.selectList(wrapper);

        EntityWrapper<NetworkDelivery> wrapper0 = new EntityWrapper<NetworkDelivery>();
        wrapper0.in("lnglat_id",rFalse);
        wrapper0.eq("batch_id",id);
        List<NetworkDelivery> ListFalseSon0=networkDeliveryService.selectList(wrapper0);
        if(ListFalseSon0.size()==0){
            return false;
        }
        String lnglat1[]=new String[ListFalseSon0.size()];
        for (int i=0;i<ListFalseSon0.size();i++){
            lnglat1[i]=ListFalseSon0.get(i).getId().toString();
        }

        EntityWrapper<NetworkDelivery> wrapper1 = new EntityWrapper<NetworkDelivery>();
        wrapper1.in("pid",lnglat1);
        wrapper1.eq("batch_id",id);
        List<NetworkDelivery> ListFalseSon=networkDeliveryService.selectList(wrapper1);

        for (int i=0;i<ListFalseSon.size();i++){
            List<Double> hashMap=new ArrayList<Double>();
            for(int j=0;j<ListTrue.size();j++){
                double distance;
                distance = CityUtil.getDistance(ListTrue.get(j).getCoordinateX().doubleValue(), ListTrue.get(j).getCoordinateY().doubleValue(),
                        ListFalseSon.get(i).getCoordinateX().doubleValue(), ListFalseSon.get(i).getCoordinateY().doubleValue());
                hashMap.add(distance);
            }
            int min=0;double minDistance=hashMap.get(0);
            for (int j1=0;j1<hashMap.size();j1++){
                if(hashMap.get(j1)<=minDistance){
                    min=j1;
                    minDistance=hashMap.get(j1);
                }
            }
            ListFalseSon.get(i).setpId(ListTrue.get(min).getId());
            ListTrue.get(min).setOrderQuantity(ListTrue.get(min).getOrderQuantity().add(ListFalseSon.get(i).getOrderQuantity()));
        }
        Boolean boolean1 = networkDeliveryService.updateBatchById(ListFalseSon);
        networkDeliveryService.updateBatchById(ListTrue);
        for(int i=0;i<rFalse.length;i++){
            EntityWrapper<NetworkDelivery> wrapper3 = new EntityWrapper<NetworkDelivery>();
            wrapper3.eq("lnglat_id",rFalse[i]);
            wrapper3.eq("batch_id",id);
            networkDeliveryService.delete(wrapper3);
        }
        EntityWrapper<OrderData> wrapper2 = new EntityWrapper<OrderData>();
        wrapper2.in("branch_id",rFalse);
        wrapper2.eq("batch_id",id);
        List<OrderData> orderDataList=orderDataService.selectList(wrapper2);

        for(int i=0;i<orderDataList.size();i++){
            List<Double> hashMap=new ArrayList<Double>();
            for(int j=0;j<ListTrue.size();j++){
                double distance;
                distance = CityUtil.getDistance(ListTrue.get(j).getCoordinateX().doubleValue(), ListTrue.get(j).getCoordinateY().doubleValue(),
                        Double.valueOf(orderDataList.get(i).getDeliveryLng()),Double.valueOf(orderDataList.get(i).getDeliveryLat()));
                hashMap.add(distance);
            }
            int min=0;double minDistance=hashMap.get(0);
            for (int j1=0;j1<hashMap.size();j1++){
                if(hashMap.get(j1)<=minDistance){
                    min=j1;
                    minDistance=hashMap.get(j1);
                }
            }
            orderDataList.get(i).setBranchCenter(ListTrue.get(min).getName());
            orderDataList.get(i).setBranchId(ListTrue.get(min).getLnglatId());
            orderDataList.get(i).setBranchLng(ListTrue.get(min).getCoordinateX().toString());
            orderDataList.get(i).setBranchLat(ListTrue.get(min).getCoordinateY().toString());
        }
        Boolean boolean2 = orderDataService.updateBatchById(orderDataList);
        if(boolean1&&boolean2){
            return true;
        }
        return false;
    }

    /**
     * 知道id,获取数据，展示到前台
     * @param id
     * @param list0
     * @return
     */
    public JSONObject getResult(String id,List<NetworkDelivery> list0){
        JSONObject jsonObject=new JSONObject();
        //数据查询处理
        EntityWrapper<NetworkDelivery> wrapper = new EntityWrapper<NetworkDelivery>();
        wrapper.eq("batch_id", id);
        wrapper.eq("operator_id", getCurrentUserId());
        List<NetworkDelivery> networkDeliveries = networkDeliveryDao.selectList(wrapper);
        List<NetworkDelivery> firstDeliveryList = new ArrayList<NetworkDelivery>();
        List<NetworkDelivery> secondDeliveryList = new ArrayList<NetworkDelivery>();
        for (NetworkDelivery delivery : networkDeliveries) {
            if (delivery.getType() == 1) {
                firstDeliveryList.add(delivery);
            }if(delivery.getType()==2) {
                secondDeliveryList.add(delivery);
            }
        }

        //进行2个算法处理，得到对应的地址
        SiteSelectionBuilderTwo builder = new SiteSelectionBuilderTwo(firstDeliveryList, secondDeliveryList);
        List<SiteSelection> siteSelectionList = builder.build(list0);

        SiteCoverBuilder builder1=new SiteCoverBuilder(siteSelectionList,secondDeliveryList);
        Map<SiteSelection, List<SiteSelection>> map=builder1.build();

//        Map<SiteSelection, List<SiteSelection>> map=getDistanceAlgorithm(siteSelectionList,secondDeliveryList);

        //对得到的算法进行处理，用来展示百度地图
       JSONArray jsonArray=getbaiduMap(map);
        jsonObject.put("Map1",jsonArray);

        //对算法结果进行处理，获取到对应的运输成本分析
        JSONObject jsonObject1=getTransport(map);
        jsonObject.put("Transport",jsonObject1);

        //对得到的算法进行处理，处理得到库存持有成本分析
        JSONObject jsonObject2=getInventory(map,id);
        jsonObject.put("Inventory",jsonObject2);

        //对所有的进行分析
        JSONObject jsonObject3=getTransportInventory(map,id);
        jsonObject.put("TransportInventory",jsonObject3);

        return jsonObject;
    }
    public Map<SiteSelection, List<SiteSelection>> getDistanceAlgorithm(List<SiteSelection> siteSelectionList,List<NetworkDelivery> secondDeliveryList){
        Map<SiteSelection, List<SiteSelection>> map=new LinkedHashMap<SiteSelection, List<SiteSelection>>();
        for(int i=0;i<siteSelectionList.size();i++){
            List<SiteSelection> list=new ArrayList<SiteSelection>();
            map.put(siteSelectionList.get(i),list);
        }
        for(int i=0;i<secondDeliveryList.size();i++){
            List<Double> list=new ArrayList<Double>();
            for(Map.Entry<SiteSelection, List<SiteSelection>> entry : map.entrySet()){
                double distance;
                distance = CityUtil.getDistance(entry.getKey().getCoordinateX().doubleValue(), entry.getKey().getCoordinateY().doubleValue(),
                        secondDeliveryList.get(i).getCoordinateX().doubleValue(),secondDeliveryList.get(i).getCoordinateY().doubleValue());
                list.add(distance);
            }
            int min=0;double minDistance=list.get(0);
            for (int j1=0;j1<list.size();j1++){
                if(list.get(j1)<=minDistance){
                    min=j1;
                    minDistance=list.get(j1);
                }
            }
            List<SiteSelection> list1=map.get(siteSelectionList.get(min));
            SiteSelection selection=SiteSelection.transform(secondDeliveryList.get(i));
            list1.add(selection);
            map.put(siteSelectionList.get(min),list1);
        }
        return map;
    }
    public JSONObject getTransportInventory(Map<SiteSelection, List<SiteSelection>> map,String id){
        ParamMap<String, Object> pm = getParameterMap();
        List<NetworkDelivery> deliveryList = new ArrayList<NetworkDelivery>();
        Long id1 = 0l;
        for (Map.Entry<SiteSelection, List<SiteSelection>> entry : map.entrySet()) {
            NetworkDelivery delivery = SiteSelection.transform(entry.getKey());
            delivery.setId(id1);
            delivery.setType(1);
            deliveryList.add(delivery);
            for (SiteSelection child : entry.getValue()) {
                delivery = SiteSelection.transform(child);
                delivery.setType(2);
                delivery.setpId(id1);
                deliveryList.add(delivery);
            }
            id1++;
        }
        JSONObject ret = calcs(pm, deliveryList);
        JSONObject ret1 = null;
        ret1=bars1(pm,map,id);
        ret.putAll(ret1);
        return ret;
    }
    private JSONObject calcs(ParamMap<String, Object> pm, List<NetworkDelivery> deliveryList) {
        //拆分一级、二级
        List<NetworkDelivery> firstDeliveryList = new ArrayList<NetworkDelivery>();
        List<Double> distanceList = new ArrayList<Double>();
        List<Double> orderList = new ArrayList<Double>();
        List<Double> costList = new ArrayList<Double>();
        List<Integer> vehicleList = new ArrayList<Integer>();
        double storeUnitPrice = pm.getDouble("storeUnitPrice");
        double area = pm.getDouble("area");
        for (NetworkDelivery delivery : deliveryList) {
            if (delivery.getType() == 1) {
                firstDeliveryList.add(delivery);
                distanceList.add(calcDistances(delivery, deliveryList));
                orderList.add(calcOrder(delivery, deliveryList));
                costList.add(calcCost(delivery, deliveryList,pm));
                vehicleList.add(calcVehicle(delivery, deliveryList,pm) );
            }
        }
        JSONArray classify = new JSONArray();
        JSONObject data;
        double totalOrder = 0d;
        double totalDistance = 0d;
        double totalCost = 0d;
        double totalVehicle = 0d;
        double renta = storeUnitPrice * area * 30;
        for (int i = 0; i < firstDeliveryList.size(); i++) {
            data = new JSONObject();
            NetworkDelivery delivery = firstDeliveryList.get(i);
            double distance = distanceList.get(i);
            data.put("name", delivery.getName());
            data.put("coordinateX", delivery.getCoordinateX());
            data.put("coordinateY", delivery.getCoordinateY());
            data.put("order", orderList.get(i));
            data.put("distance", distance);
            data.put("cost", costList.get(i));
            data.put("vehicle", vehicleList.get(i));
            totalOrder += orderList.get(i).doubleValue();
            totalDistance += distance;
            totalCost +=  costList.get(i);
            totalVehicle += vehicleList.get(i);
            classify.add(data);
        }
        totalCost += renta;
        JSONObject ret = new JSONObject();
        ret.put("data", classify);
        ret.put("totalOrder", df.format(totalOrder));
        ret.put("totalDistance", df.format(totalDistance));
        ret.put("totalCost", df.format(totalCost));
        ret.put("totalVehicle", totalVehicle);
        ret.put("renta", df.format(renta));
        return ret;
    }


    public JSONObject bars1(ParamMap<String, Object> pm,Map<SiteSelection, List<SiteSelection>> map,String id){
        //创建JSON用于view层
        JSONObject ret = new JSONObject();
        JSONArray array1=new JSONArray();
        JSONArray array2=new JSONArray();
        JSONArray array3=new JSONArray();
        JSONArray array4=new JSONArray();
        JSONArray array5=new JSONArray();
        //batch_id的所有order数据
        EntityWrapper<OrderData> wrapper = new EntityWrapper<OrderData>();
        wrapper.eq("batch_id",id);
        List<OrderData> order1 = orderDataService.selectList(wrapper);
        //一级配送中心循环
        for (Map.Entry<SiteSelection, List<SiteSelection>> entry:map.entrySet()){
            List<Long> stringList=new ArrayList<Long>();
            //一级配送下面的二级配送中心
            for(int i=0;i<entry.getValue().size();i++){
                stringList.add(entry.getValue().get(i).getLnglatId());
            }
            //几个2级中心的所有order数据group by配车制单日期
            Map<String,Object> pm1=new HashMap<String,Object>();
            pm1.put("delivery",stringList);
            pm1.put("batchId",id);
            List<Map<String, Object>> s2 = orderDataDao.select2(pm1);
            //生成s1数据，和总的需求量simulateDemandSum
            List<SiteSelection> selectionList=entry.getValue();
            SiteSelection s0=entry.getKey();
            double simulateDemandSum=0;
            List<OrderData> s1=new ArrayList<OrderData>();
            for(int i=0;i<selectionList.size();i++){
                for (int j=0;j<order1.size();j++){
                    if (selectionList.get(i).getLnglatId().equals(order1.get(j).getDeliveryId())){
                        s1.add(order1.get(j));
                    }
                }
                simulateDemandSum=simulateDemandSum+Double.valueOf(selectionList.get(i).getOrder().toString());
            }
            array1.add(entry.getKey().getName());
            //通过moneyLevel1方法，获取数据
            try{
                HashMap<String,Integer> hashMap=moneyLevel1(s0,s1,s2,pm,simulateDemandSum);
                array2.add(hashMap.get("moneyLevel"));
                array3.add(hashMap.get("avgInventory"));
            }catch (Exception e){
                String message="上传数据不完整，请检查数据";
                ret.put("time",message);
                return ret;
            }
        }
        ret.put("x1",array1);
        ret.put("x2",array2);//订货周期内库存商品占用资金水平
        ret.put("x3",array3);//订货周期内的平均库存
        ret.put("x4",array4);
        ret.put("x5",array5);//各一级配送中心平均订单完成率分布
        return ret;
    }

    public HashMap<String,Integer> moneyLevel1(SiteSelection map,List<OrderData> inventoryCostAfterList,List<Map<String, Object>> inventoryCostList2,ParamMap<String, Object> pms,double simulateDemandSum){
        //对pm进行处理
        String prices=pms.get("prize").toString();
        String dealTime=pms.get("dealTime").toString();
        String holdCost=pms.get("holdCost").toString();
        String orderCost=pms.get("orderCost").toString();
        String month=pms.get("months").toString();
        double price=Double.valueOf(prices);
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");//创建日期转换对象HH:mm:ss为时分秒，年月日为yyyy-MM-dd
        List<Long> list=new ArrayList<Long>();
        Long advanceTimeSum=0L;
        //处理得到服务水平 提前期 所需要的数据
        for (int i=0;i<inventoryCostAfterList.size();i++){
            int days=node1ToNode2Distance(Double.valueOf(map.getCoordinateY().toString()),Double.valueOf(map.getCoordinateX().toString()),Double.valueOf(inventoryCostAfterList.get(i).getFactoryLat()),Double.valueOf(inventoryCostAfterList.get(i).getFactoryLng()))+Integer.valueOf(dealTime);
            list.add(Long.valueOf(String.valueOf(days)));
            advanceTimeSum=advanceTimeSum+days;
        }
        //服务水平
        String serviceLevelString=pms.get("costomService").toString();
        //计算提前期的标准差
        double advanceAvg=((double)advanceTimeSum)/((double)inventoryCostAfterList.size());
        double advanceStandard=0;
        for (int i=0;i<list.size();i++){
            advanceStandard=advanceStandard+(list.get(i)-advanceAvg)*(list.get(i)-advanceAvg);
        }
        int demandSum=0;
        for (int i=0;i<inventoryCostList2.size();i++){
            demandSum=demandSum+Integer.valueOf(inventoryCostList2.get(i).get("ordersum").toString());
        }
        double demadAvg=demandSum/inventoryCostList2.size();
        //计算的日需求量标准差
        double demadStandard=0;
        for (int i=0;i<inventoryCostList2.size();i++){
            demadStandard=demadStandard+(Integer.valueOf(inventoryCostList2.get(i).get("ordersum").toString())-demadAvg)*(Integer.valueOf(inventoryCostList2.get(i).get("ordersum").toString())-demadAvg);
        }
        double z=ZvalueUtil.getZ(serviceLevelString);
        double value= z*Math.sqrt(demadStandard/inventoryCostList2.size()*advanceAvg+advanceStandard/list.size()*demadAvg*demadAvg);
        //一级配送中心再订货点
        double orderPort=value+demadAvg*advanceAvg;
        // 经济订货批量(EOQ)
        double eoq=Math.sqrt(2*simulateDemandSum*Integer.valueOf(orderCost)/Integer.valueOf(holdCost));
        //订货周期内的周转库存
        double turnoverInventory;
        double dateInterval=0;
        for (int i=1;i<=inventoryCostList2.size();i++){
            try{
                Date preparationCar1=df.parse(inventoryCostList2.get(i-1).get("preparationCar").toString());
                Date preparationCar2=df.parse(inventoryCostList2.get(i).get("preparationCar").toString());
                long diff=preparationCar2.getTime()-preparationCar1.getTime();
                long days=diff/(1000*60*60*24);
                dateInterval=dateInterval+days;
            }catch (Exception e){
            }
        }
        double dateIntervalAvg=dateInterval/inventoryCostList2.size();
        turnoverInventory=demadAvg*(30*eoq*Integer.valueOf(month)/simulateDemandSum);
        //订货周期内的最大库存
        double maxInventory=turnoverInventory+value;
        //订货周期内的平均库存
        double avgInventory=value+turnoverInventory/2;
        //订货周期内库存商品占用资金水平
        double moneyLevel=avgInventory*price;
        //一级配送中心1个月的平均库存
        double months=30;
        double monthAvgInventory=(months/dateIntervalAvg)*avgInventory;
        HashMap<String,Integer> hashMap=new HashMap<String, Integer>();
        hashMap.put("moneyLevel",1+(int)moneyLevel);
        hashMap.put("avgInventory",1+(int)avgInventory);
        return hashMap;
    }
    /**
     * 计算总订单量
     */
    private double calcOrder(NetworkDelivery first, List<NetworkDelivery> deliveryList) {
        double order = 0d;
        for (NetworkDelivery second : deliveryList) {
            if (first.getId().equals(second.getpId())) {
                order += second.getOrderQuantity().doubleValue();
            }
        }
        return order;
    }
    /**
     * 计算总订单量
     */
    private int calcVehicle(NetworkDelivery first, List<NetworkDelivery> deliveryList,ParamMap<String,Object> pm) {
        double load = pm.getDouble("load");
        double volume = pm.getDouble("volume");
        double months=pm.getDouble("months");
        int vehicle = 0;
        for (NetworkDelivery second : deliveryList) {
            if (first.getId().equals(second.getpId())) {
                vehicle += (int) Math.ceil(second.getOrderQuantity().doubleValue() * volume / load / 30/months);
            }
        }
        return vehicle;
    }

    /**
     * 计算总订单量
     */
    private double calcCost(NetworkDelivery first, List<NetworkDelivery> deliveryList,ParamMap<String, Object> pm) {
        double unitPrice = pm.getDouble("unitPrice");
        double volume = pm.getDouble("volume");
        double load = pm.getDouble("load");
        double otherExpenses = pm.getDouble("otherExpenses");
        double months=pm.getDouble("months");
        double cost = 0d;
        for (NetworkDelivery second : deliveryList) {
            if (first.getId().equals(second.getpId())) {
                double distance =CityUtil.getDistance(first.getCoordinateX().doubleValue(), first.getCoordinateY().doubleValue(),
                        second.getCoordinateX().doubleValue(), second.getCoordinateY().doubleValue());
                int vehicle =   (int) Math.ceil(second.getOrderQuantity().doubleValue() * volume / load / 30/months);
                cost += unitPrice * vehicle * distance + otherExpenses;
            }
        }
        return cost;
    }

    public JSONObject getInventory(Map<SiteSelection, List<SiteSelection>> selection,String id){
        ParamMap<String, Object> pm = getParameterMap();
        //算出一级中心siteSelection1，二级中心selectionList
        List<SiteSelection> selectionList=new ArrayList<SiteSelection>();
        SiteSelection siteSelection1=new SiteSelection();
        for (Map.Entry<SiteSelection, List<SiteSelection>> map:selection.entrySet()){
            if(pm.get("name").toString().length()==0){
                selectionList=map.getValue();
                siteSelection1=map.getKey();
                break;
            }
            if (map.getKey().getName().equals(pm.get("name").toString())){
                selectionList=map.getValue();
                siteSelection1=map.getKey();
            }
        }
        //得到2级中心和总需求量
        double simulateDemandSum=0;
        List<Long> stringList=new ArrayList<Long>();
        for(int i=0;i<selectionList.size();i++){
            stringList.add(selectionList.get(i).getLnglatId());
            simulateDemandSum=simulateDemandSum+Double.valueOf(selectionList.get(i).getOrder().toString());
        }
        //得到2级中心所有数据
        EntityWrapper<OrderData> wrapper = new EntityWrapper<OrderData>();
        wrapper.eq("batch_id",id);
        wrapper.in("delivery_id",stringList);
        List<OrderData> inventoryCostAfterList = orderDataService.selectList(wrapper);
        //根据配车制单日期得到order数据
        Map<String,Object> pm1=new HashMap<String,Object>();
        pm1.put("delivery",stringList);
        pm1.put("batchId",id);
        List<Map<String, Object>> inventoryCostList2 = orderDataDao.select2(pm1);
        //根据getAll方法，得到ret数据
        JSONObject ret = getAll(siteSelection1,inventoryCostAfterList,inventoryCostList2,pm,simulateDemandSum);
        return ret;
    }
    public JSONObject getAll(SiteSelection map,List<OrderData> inventoryCostAfterList,List<Map<String, Object>> inventoryCostList2,ParamMap<String, Object> pms,double simulateDemandSum){
        String prices=pms.get("prize").toString();
        String dealTime=pms.get("dealTime").toString();
        String holdCost=pms.get("holdCost").toString();
        String orderCost=pms.get("orderCost").toString();
        String month=pms.get("months").toString();
        double price=Double.valueOf(prices);
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");//创建日期转换对象HH:mm:ss为时分秒，年月日为yyyy-MM-dd
        List<Long> list=new ArrayList<Long>();
        Long advanceTimeSum=0L;
        //处理得到服务水平 提前期 所需要的数据
        for (int i=0;i<inventoryCostAfterList.size();i++){
            int days=node1ToNode2Distance(Double.valueOf(map.getCoordinateY().toString()),Double.valueOf(map.getCoordinateX().toString()),Double.valueOf(inventoryCostAfterList.get(i).getFactoryLat()),Double.valueOf(inventoryCostAfterList.get(i).getFactoryLng()))+Integer.valueOf(dealTime);
            list.add(Long.valueOf(String.valueOf(days)));
            advanceTimeSum=advanceTimeSum+days;
        }
        //服务水平
        String serviceLevelString=pms.get("costomService").toString();
        //计算提前期的标准差
        double advanceAvg=((double)advanceTimeSum)/((double)inventoryCostAfterList.size());
        double advanceStandard=0;
        for (int i=0;i<list.size();i++){
            advanceStandard=advanceStandard+(list.get(i)-advanceAvg)*(list.get(i)-advanceAvg);
        }
        int demandSum=0;
        for (int i=0;i<inventoryCostList2.size();i++){
            demandSum=demandSum+Integer.valueOf(inventoryCostList2.get(i).get("ordersum").toString());
        }
        double demadAvg=demandSum/inventoryCostList2.size();
        //计算的日需求量标准差
        double demadStandard=0;
        for (int i=0;i<inventoryCostList2.size();i++){
            demadStandard=demadStandard+(Integer.valueOf(inventoryCostList2.get(i).get("ordersum").toString())-demadAvg)*(Integer.valueOf(inventoryCostList2.get(i).get("ordersum").toString())-demadAvg);
        }
        double z=ZvalueUtil.getZ(serviceLevelString);
        double value= z*Math.sqrt(demadStandard/inventoryCostList2.size()*advanceAvg+advanceStandard/list.size()*demadAvg*demadAvg);
        //一级配送中心再订货点
        double orderPort=value+demadAvg*advanceAvg;
        // 经济订货批量(EOQ)
        double eoq=Math.sqrt(2*simulateDemandSum*Integer.valueOf(orderCost)/Integer.valueOf(holdCost));
        //订货周期内的周转库存
        double turnoverInventory;
        double dateInterval=0;
        for (int i=1;i<=inventoryCostList2.size();i++){
            try{
                Date preparationCar1=df.parse(inventoryCostList2.get(i-1).get("preparationCar").toString());
                Date preparationCar2=df.parse(inventoryCostList2.get(i).get("preparationCar").toString());
                long diff=preparationCar2.getTime()-preparationCar1.getTime();
                long days=diff/(1000*60*60*24);
                dateInterval=dateInterval+days;
            }catch (Exception e){
            }
        }
        double dateIntervalAvg=dateInterval/inventoryCostList2.size();
        turnoverInventory=demadAvg*(30*eoq*Integer.valueOf(month)/simulateDemandSum);
        //订货周期内的最大库存
        double maxInventory=turnoverInventory+value;
        //订货周期内的平均库存
        double avgInventory=value+turnoverInventory/2;
        //订货周期内库存商品占用资金水平
        double moneyLevel=avgInventory*price;
        //一级配送中心1个月的平均库存
        double months=30;
        double monthAvgInventory=(months/dateIntervalAvg)*avgInventory;
        //到各二级配送中心的总订单量
        double toSecondaryCenter=simulateDemandSum;
        JSONObject ret =new JSONObject();
        ret.put("safetyStock",1+(int)value);
        ret.put("orderPort",1+(int)orderPort);
        ret.put("turnoverInventory",1+(int)turnoverInventory);
        ret.put("maxInventory",1+(int)maxInventory);
        ret.put("eoq",1+(int)eoq);
        ret.put("moneyLevel",1+(int)moneyLevel);
        ret.put("avgInventory",1+(int)avgInventory);
        ret.put("toSecondaryCenter",1+(int)toSecondaryCenter);
        return ret;
    }

    public  int node1ToNode2Distance(double wd1,double jd1,double wd2,double jd2)
    {
        double x,y,out;
        double PI=3.14159265;
        double R=6.371229*1e6;

        x=(jd2-jd1)*PI*R*Math.cos( ((wd1+wd2)/2) *PI/180)/180;
        y=(wd2-wd1)*PI*R/180;
        out=Math.hypot(x,y);
        int time=1+(int)(out/1000)/60/24;
        return time;
    }


    /**
     * 运输相关数据获取
     * @param map
     * @return
     */
    public JSONObject getTransport(Map<SiteSelection, List<SiteSelection>> map){
        ParamMap<String, Object> pm = getParameterMap();
        NetworkDelivery first = null;
        List<NetworkDelivery> secondList = new ArrayList<NetworkDelivery>();
        for (SiteSelection siteSelection : map.keySet()) {
            if(pm.getString("name").length()==0){
                first = SiteSelection.transform(siteSelection);
                for (SiteSelection child : map.get(siteSelection)) {
                    secondList.add(SiteSelection.transform(child));
                }
                break;
            }
            if (siteSelection.getName().equals(pm.getString("name"))) {
                first = SiteSelection.transform(siteSelection);
                for (SiteSelection child : map.get(siteSelection)) {
                    secondList.add(SiteSelection.transform(child));
                }
            }
        }
        JSONObject ret = calc(pm, first, secondList);
        return ret;
    }

    /**
     * 运输数据的处理，返回结果
     * @param pm
     * @param first
     * @param secondList
     * @return
     */
    private JSONObject calc(ParamMap<String, Object> pm, NetworkDelivery first, List<NetworkDelivery> secondList) {
        List<Double> distanceList = calcDistance(first, secondList);
        double unitPrice = pm.getDouble("unitPrice");
        double volume = pm.getDouble("volume");
        double load = pm.getDouble("load");
        double otherExpenses = pm.getDouble("otherExpenses");
        double storeUnitPrice = pm.getDouble("storeUnitPrice");
        double area = pm.getDouble("area");
        double months=pm.getDouble("months");
        JSONArray classify = new JSONArray();
        JSONObject data;
        double totalOrder = 0d;
        double totalDistance = 0d;
        double totalCost = 0d;
        double totalVehicle = 0d;
        double renta = storeUnitPrice * area * 30;
        for (int i = 0; i < secondList.size(); i++) {
            data = new JSONObject();
            NetworkDelivery delivery = secondList.get(i);
            double distance = distanceList.get(i);
            double vehicle = (int) Math.ceil(delivery.getOrderQuantity().doubleValue() * volume / load / 30/months);
            double cost = unitPrice * vehicle * distance + otherExpenses;
            data.put("name", delivery.getName());
            data.put("coordinateX", delivery.getCoordinateX());
            data.put("coordinateY", delivery.getCoordinateY());
            data.put("order", delivery.getOrderQuantity());
            data.put("distance", distance);
            data.put("cost", cost);
            data.put("vehicle", vehicle);
            totalOrder += delivery.getOrderQuantity().doubleValue();
            totalDistance += distance;
            totalCost += cost;
            totalVehicle += vehicle;
            classify.add(data);
        }
        totalCost += renta;
        JSONObject ret = new JSONObject();
        ret.put("data", classify);
        ret.put("totalOrder", df.format(totalOrder));
        ret.put("totalDistance", df.format(totalDistance));
        ret.put("totalCost", df.format(totalCost));
        ret.put("totalVehicle", totalVehicle);
        ret.put("renta", df.format(renta));
        return ret;
    }

    /**
     * 计算距离
     */
    private List<Double> calcDistance(NetworkDelivery first, List<NetworkDelivery> secondList) {
        List<Double> distanceList = new ArrayList<Double>(secondList.size());
        double distance;
        for (NetworkDelivery second : secondList) {
            distance = CityUtil.getDistance(first.getCoordinateX().doubleValue(), first.getCoordinateY().doubleValue(),
                    second.getCoordinateX().doubleValue(), second.getCoordinateY().doubleValue());
            distanceList.add(distance);
        }
        return distanceList;
    }
    /**
     * 计算距离
     */
    private double calcDistances(NetworkDelivery first, List<NetworkDelivery> deliveryList) {
        double distance = 0d;
        for (NetworkDelivery second : deliveryList) {
            if (first.getId().equals(second.getpId())) {
                distance += CityUtil.getDistance(first.getCoordinateX().doubleValue(), first.getCoordinateY().doubleValue(),
                        second.getCoordinateX().doubleValue(), second.getCoordinateY().doubleValue());
            }
        }
        return distance;
    }


    /**
     * 地图展示的所需数据的获取
     * @param map
     * @return
     */

    public JSONArray getbaiduMap(Map<SiteSelection, List<SiteSelection>> map){
        JSONArray data = new JSONArray();
        String startnode=null;
        Random random = new Random(47);
        for (Map.Entry<SiteSelection,List<SiteSelection>> entry:map.entrySet()){
            JSONArray nodes = new JSONArray();
            JSONArray res = new JSONArray();
            JSONObject serie=new JSONObject();
            startnode=entry.getKey().getName();
            for(int j=0;j<entry.getValue().size();j++){
                nodes.add(new NodeData(startnode, Arrays.asList(entry.getValue().get(j).getCoordinateX(),entry.getValue().get(j).getCoordinateY(), random.nextInt(100))));
                JSONObject res1 = parseRes(entry,j);
                res.add(res1);
            }
            serie.put("name",startnode);
            serie.put("res", res);
            serie.put("nodes", nodes);
            data.add(serie);
        }
        return data;
    }


    //对res进行处理
    private JSONObject parseRes(Map.Entry<SiteSelection,List<SiteSelection>> entry,int j) {
        JSONObject res = new JSONObject();
        res.put("fromName",entry.getKey().getName());
        res.put("toName", entry.getValue().get(j).getName());
        JSONArray fromCoord = new JSONArray();
        fromCoord.add(entry.getKey().getCoordinateX());
        fromCoord.add(entry.getKey().getCoordinateY());
        JSONArray toCoord = new JSONArray();
        toCoord.add(entry.getValue().get(j).getCoordinateX());
        toCoord.add(entry.getValue().get(j).getCoordinateY());
        JSONArray coords = new JSONArray();
        coords.add(fromCoord);
        coords.add(toCoord);
        res.put("coords", coords);
        return res;
    }






}
